﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Facebook;
using NutriLeaf.Web.Model;
using NutriLeaf.Web.Core.Account;

namespace NutriLeaf.Web.Core.Friends
{
    public class Friends
    {

        /// <summary>
        /// Gets the ID of all the friends who are on facebook
        /// </summary>
        /// <param name="accessToken">Access token needed by the Facebook Application</param>
        /// <returns></returns>
        public static List<int> GetFacebookFriendsID(string accessToken)
        {
            FacebookClient fb = new FacebookClient(accessToken);
            dynamic myInfo = fb.Get("/me/friends");

            List<int> friendsId = new List<int>();

            foreach (dynamic friend in myInfo.data)
            {
                friendsId.Add(Convert.ToInt32(friend.id));
            }

            return friendsId;

        }

        /// <summary>
        /// Gets the Id's of the friends who are on Facebook and registered with Nutri Leaf
        /// </summary>
        /// <param name="accessToken">Access token required by Facebook</param>
        /// <returns></returns>
        public static List<int> GetRegisteredFacebookFriendsID(string accessToken,ref NutriLeafDBEntities context)
        {
            List<int> friends = GetFacebookFriendsID(accessToken);
            List<int> registeredFriendList = new List<int>();
            foreach(int friendId in friends)
            {
                if (Account.User.IsRegistered(friendId, ref context))
                {
                    registeredFriendList.Add(friendId);
                }
            }

            return registeredFriendList;
        }

        public static void SendFriendRequestToFacebookFriends(string accessToken, ref NutriLeafDBEntities context)
        {
            List<int> friendIDs = GetRegisteredFacebookFriendsID(accessToken,ref context);

            int userId = Account.User.GetUserID(accessToken, ref context);

            foreach (int friendID in friendIDs)
            {
                if(!FriendRequestExists(userId,friendID,ref context))
                {
                    Model.Friend friend = new Friend();
                    friend.RequestBlocked = false;
                    friend.RequestAccepted = false;
                    friend.RequestIgnored = false;
                    friend.User1ID = userId;
                    friend.User2ID = friendID;
                    friend.DateTimeStamp = DateTime.Now;
                    context.AddToFriends(friend);
                }

                context.SaveChanges();
            }

        }

        public static void SendFriendRequest(int user1Id, int user2Id, ref NutriLeafDBEntities context)
        {
            Model.Friend friend = GetFriendRelationship(user1Id, user2Id, ref context);

            if (friend != null)
            {
                throw new Exceptions.Friends.FriendRequestAlreadyExistsException("Friend request already exists");
            }

            friend = new Friend();
            friend.User1ID = user1Id;
            friend.User2ID = user2Id;
            friend.RequestAccepted = false;
            friend.RequestBlocked = false;
            friend.RequestIgnored = false;

            friend.DateTimeStamp = DateTime.Now;

            context.AddToFriends(friend);
            context.SaveChanges();

        }

        public static List<Model.Friend> GetPendingFriendRequestRelationships(int userId, ref NutriLeafDBEntities context)
        {
            return (from a in context.Friends
                    where a.User2ID == userId && a.RequestAccepted == false && a.RequestIgnored==false && a.RequestBlocked==false
                    select a).ToList();
        }

        public static List<UserData> GetPendingFriendRequestUserData(int userId, ref NutriLeafDBEntities context)
        {
            List<Friend> friends = GetPendingFriendRequestRelationships(userId, ref context);

            List<UserData> userData = new List<UserData>();

            foreach (Friend friend in friends)
            {
                userData.Add(Core.Account.User.GetUserData(friend.User1ID,ref context));
            }

            return userData;

        }

        public static List<Model.Friend> GetAwaitingApprovalFriendRequestRelationships(int userId, ref NutriLeafDBEntities context)
        {
            return (from a in context.Friends
                    where a.User1ID == userId && a.RequestAccepted == false && a.RequestIgnored == false && a.RequestBlocked == false
                    select a).ToList();
        }

        public static List<UserData> GetAwaitingApprovalRequestUserData(int userId, ref NutriLeafDBEntities context)
        {
            List<Friend> friends = GetAwaitingApprovalFriendRequestRelationships(userId, ref context);

            List<UserData> userData = new List<UserData>();

            foreach (Friend friend in friends)
            {
                userData.Add(Core.Account.User.GetUserData(friend.User1ID,ref context));
            }

            return userData;
        }

        public static void AcceptFriendRequest(int user1Id, int user2Id, ref NutriLeafDBEntities context)
        {
            Model.Friend friend = GetFriendRelationship(user2Id, user1Id, ref context);

            friend.RequestAccepted = true;

            context.SaveChanges();

        }

        public static void AcceptFriendRequest(Model.Friend friend, ref NutriLeafDBEntities context)
        {
            friend.RequestAccepted = true;

            context.SaveChanges();
        }

        public static void IgnoreFriendRequest(Model.Friend friend, ref NutriLeafDBEntities context)
        {
            friend.RequestIgnored = true;

            context.SaveChanges();
        }

        public static void IgnoreFriendRequest(int user1Id, int user2Id, ref NutriLeafDBEntities context)
        {
            Model.Friend friend = GetFriendRelationship(user2Id, user1Id, ref context);

            friend.RequestIgnored = true;

            context.SaveChanges();
        }

        public static Model.Friend GetFriendRelationship(int user1Id, int user2Id, ref NutriLeafDBEntities context)
        {
            return (from a in context.Friends
                                   where a.User1ID == user1Id && a.User2ID == user2Id
                                   select a).SingleOrDefault();
        }

        public static void AcceptAllPendingRequests(List<Model.Friend> friends, ref NutriLeafDBEntities context)
        {
            foreach (Model.Friend friend in friends)
            {
                friend.RequestAccepted = true;
            }

            context.SaveChanges();
        }

        public static void AcceptAllPendingRequests(int userId, ref NutriLeafDBEntities context)
        {
            List<Model.Friend> friends = GetPendingFriendRequestRelationships(userId, ref context);

            foreach (Model.Friend friend in friends)
            {
                friend.RequestAccepted = true;
            }

            context.SaveChanges();
        }

        public static void IgnoreAllPendingRequests(int userId, ref NutriLeafDBEntities context)
        {
            List<Model.Friend> friends = GetPendingFriendRequestRelationships(userId, ref context);

            foreach (Model.Friend friend in friends)
            {
                friend.RequestIgnored = true;
            }

            context.SaveChanges();
        }

        public static void IgnoreAllPendingRequests(List<Model.Friend> friends, ref NutriLeafDBEntities context)
        {
            foreach (Model.Friend friend in friends)
            {
                friend.RequestIgnored = true;
            }

            context.SaveChanges();
        }
       
        public static bool FriendRequestExists(int User1Id, int User2Id, ref NutriLeafDBEntities context)
        {
            Model.Friend friendRelationship = (from a in context.Friends
                                               where (a.User1ID == User1Id && a.User2ID == User2Id) || (a.User1ID==User2Id && a.User2ID==User1Id)
                                               select a).SingleOrDefault();

            if (friendRelationship != null)
            {
                return true;
            }
            return false;
        }
    }
}